package com.hliushi.netty.protocol;

import com.alibaba.fastjson.JSONObject;
import com.hliushi.netty.message.Message;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * @author llhuang10
 * @date 2021/10/22 14:41
 */
public interface Serializer {

    /**
     * 反序列化方法
     */
    <T> T deserialize(Class<T> clazz, byte[] bytes);

    /**
     * 序列化方法
     */
    <T> byte[] serialize(T object);


    enum Algorithm implements Serializer {
        /**
         * 枚举里面的变量都一个顺序, 比如Java, Json -> 对应的顺序就为0, 1
         */

        Java {
            @Override
            public <T> T deserialize(Class<T> clazz, byte[] bytes) {
                try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
                    return (T) ois.readObject();
                } catch (IOException | ClassNotFoundException e) {
                    throw new RuntimeException("JDK反序列化失败, ex: {}", e);
                }
            }

            @Override
            public <T> byte[] serialize(T object) {
                try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
                     ObjectOutputStream oos = new ObjectOutputStream(bos)) {
                    oos.writeObject(object);
                    return bos.toByteArray();
                } catch (IOException e) {
                    throw new RuntimeException("JDK序列化失败, ex: {}", e);
                }
            }
        },

        Json {
            @Override
            public <T> T deserialize(Class<T> clazz, byte[] bytes) {
                T t = null;
                try {
                    t = JSONObject.parseObject(new String(bytes, StandardCharsets.UTF_8), clazz);
                } catch (Exception e) {
                    throw new RuntimeException("JSON反序列化失败, ex: {}", e);
                }
                return t;
            }

            @Override
            public <T> byte[] serialize(T object) {
                String jsonString = JSONObject.toJSONString(object);
                return jsonString.getBytes(StandardCharsets.UTF_8);
            }
        },

        Kryo {

            private final Serializer kryoSerializer = KryoSerializerFactory.getSerializer(Message.class);

            @Override
            public <T> T deserialize(Class<T> clazz, byte[] bytes) {
                return kryoSerializer.deserialize(clazz, bytes);
            }

            @Override
            public <T> byte[] serialize(T object) {
                return kryoSerializer.serialize(object);
            }
        }

    }
}
